Fix track filter to not "randomly" reorder points within a track when
authorrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 23 Jul 2013 06:35:53 +0000 (06:35 +0000)
committerrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 23 Jul 2013 06:35:53 +0000 (06:35 +0000)
sub-second times are in play.

Addresses problem reported March 26 2010 (sigh) by Klaus Rheinwald.

gpsbabel/reference/track/split-raw.gpx [new file with mode: 0644]
gpsbabel/reference/track/split-split.gpx [new file with mode: 0644]
gpsbabel/testo.d/track.test
gpsbabel/trackfilter.cc

diff --git a/gpsbabel/reference/track/split-raw.gpx b/gpsbabel/reference/track/split-raw.gpx
new file mode 100644 (file)
index 0000000..e346a1a
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<gpx\r
+  version="1.0"\r
+  creator="GPSBabel - http://www.gpsbabel.org"\r
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+  xmlns="http://www.topografix.com/GPX/1/0"\r
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">\r
+<time>2010-03-26T00:48:12Z</time>\r
+<bounds minlat="53.556432500" minlon="9.865178669" maxlat="53.556793494" maxlon="9.865555237"/>\r
+<trk>\r
+<trkseg>\r
+<trkpt lat="53.556633430" lon="9.865449271">\r
+  <ele>77.800034</ele>\r
+  <time>2010-03-26T00:48:08Z</time>\r
+  <speed>0.023166</speed>\r
+  <name>TP000224</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633441" lon="9.865449188">\r
+  <ele>77.799362</ele>\r
+  <time>2010-03-26T00:48:08.200Z</time>\r
+  <speed>0.031641</speed>\r
+  <name>TP000225</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633435" lon="9.865449054">\r
+  <ele>77.798965</ele>\r
+  <time>2010-03-26T00:48:08.400Z</time>\r
+  <speed>0.051357</speed>\r
+  <name>TP000226</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633447" lon="9.865448859">\r
+  <ele>77.798965</ele>\r
+  <time>2010-03-26T00:48:08.600Z</time>\r
+  <speed>0.054567</speed>\r
+  <name>TP000227</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633445" lon="9.865448672">\r
+  <ele>77.798462</ele>\r
+  <time>2010-03-26T00:48:08.800Z</time>\r
+  <speed>0.056182</speed>\r
+  <name>TP000228</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633459" lon="9.865448482">\r
+  <ele>77.798309</ele>\r
+  <time>2010-03-26T00:48:09Z</time>\r
+  <speed>0.066637</speed>\r
+  <name>TP000229</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633498" lon="9.865448276">\r
+  <ele>77.797417</ele>\r
+  <time>2010-03-26T00:48:09.200Z</time>\r
+  <speed>0.071383</speed>\r
+  <name>TP000230</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633546" lon="9.865448057">\r
+  <ele>77.795921</ele>\r
+  <time>2010-03-26T00:48:09.400Z</time>\r
+  <speed>0.081816</speed>\r
+  <name>TP000231</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633571" lon="9.865447824">\r
+  <ele>77.794380</ele>\r
+  <time>2010-03-26T00:48:09.600Z</time>\r
+  <speed>0.072754</speed>\r
+  <name>TP000232</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633547" lon="9.865447614">\r
+  <ele>77.792450</ele>\r
+  <time>2010-03-26T00:48:09.800Z</time>\r
+  <speed>0.078225</speed>\r
+  <name>TP000233</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633489" lon="9.865447399">\r
+  <ele>77.791138</ele>\r
+  <time>2010-03-26T00:48:10Z</time>\r
+  <speed>0.076833</speed>\r
+  <name>TP000234</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633408" lon="9.865447214">\r
+  <ele>77.790253</ele>\r
+  <time>2010-03-26T00:48:10.200Z</time>\r
+  <speed>0.088488</speed>\r
+  <name>TP000235</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633317" lon="9.865446987">\r
+  <ele>77.786873</ele>\r
+  <time>2010-03-26T00:48:10.400Z</time>\r
+  <speed>0.103797</speed>\r
+  <name>TP000236</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633191" lon="9.865446765">\r
+  <ele>77.784561</ele>\r
+  <time>2010-03-26T00:48:10.600Z</time>\r
+  <speed>0.103352</speed>\r
+  <name>TP000237</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633088" lon="9.865446533">\r
+  <ele>77.782021</ele>\r
+  <time>2010-03-26T00:48:10.800Z</time>\r
+  <speed>0.087818</speed>\r
+  <name>TP000238</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633048" lon="9.865446282">\r
+  <ele>77.780220</ele>\r
+  <time>2010-03-26T00:48:11Z</time>\r
+  <speed>0.081600</speed>\r
+  <name>TP000239</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633049" lon="9.865446021">\r
+  <ele>77.780632</ele>\r
+  <time>2010-03-26T00:48:11.200Z</time>\r
+  <speed>0.078945</speed>\r
+  <name>TP000240</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633074" lon="9.865445763">\r
+  <ele>77.780319</ele>\r
+  <time>2010-03-26T00:48:11.400Z</time>\r
+  <speed>0.083918</speed>\r
+  <name>TP000241</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633143" lon="9.865445484">\r
+  <ele>77.779068</ele>\r
+  <time>2010-03-26T00:48:11.600Z</time>\r
+  <speed>0.100007</speed>\r
+  <name>TP000242</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633252" lon="9.865445205">\r
+  <ele>77.778175</ele>\r
+  <time>2010-03-26T00:48:11.800Z</time>\r
+  <speed>0.099195</speed>\r
+  <name>TP000243</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633370" lon="9.865444927">\r
+  <ele>77.777702</ele>\r
+  <time>2010-03-26T00:48:12Z</time>\r
+  <speed>0.096335</speed>\r
+  <name>TP000244</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+<trkpt lat="53.556633474" lon="9.865444640">\r
+  <ele>77.777336</ele>\r
+  <time>2010-03-26T00:48:12.200Z</time>\r
+  <speed>0.097903</speed>\r
+  <name>TP000245</name>\r
+  <fix>3d</fix>\r
+</trkpt>\r
+</trkseg>\r
+</trk>\r
+</gpx>\r
diff --git a/gpsbabel/reference/track/split-split.gpx b/gpsbabel/reference/track/split-split.gpx
new file mode 100644 (file)
index 0000000..c00f603
--- /dev/null
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - http://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+  <time>1970-01-01T00:00:00Z</time>
+  <bounds minlat="53.556633048" minlon="9.865444640" maxlat="53.556633571" maxlon="9.865449271"/>
+  <trk>
+    <name>20100325194808</name>
+    <trkseg>
+      <trkpt lat="53.556633430" lon="9.865449271">
+        <ele>77.800034</ele>
+        <time>2010-03-26T00:48:08Z</time>
+        <speed>0.023166</speed>
+        <name>TP000224</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633441" lon="9.865449188">
+        <ele>77.799362</ele>
+        <time>2010-03-26T00:48:08.200Z</time>
+        <speed>0.031641</speed>
+        <name>TP000225</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633435" lon="9.865449054">
+        <ele>77.798965</ele>
+        <time>2010-03-26T00:48:08.400Z</time>
+        <speed>0.051357</speed>
+        <name>TP000226</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633447" lon="9.865448859">
+        <ele>77.798965</ele>
+        <time>2010-03-26T00:48:08.600Z</time>
+        <speed>0.054567</speed>
+        <name>TP000227</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633445" lon="9.865448672">
+        <ele>77.798462</ele>
+        <time>2010-03-26T00:48:08.800Z</time>
+        <speed>0.056182</speed>
+        <name>TP000228</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633459" lon="9.865448482">
+        <ele>77.798309</ele>
+        <time>2010-03-26T00:48:09Z</time>
+        <speed>0.066637</speed>
+        <name>TP000229</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633498" lon="9.865448276">
+        <ele>77.797417</ele>
+        <time>2010-03-26T00:48:09.200Z</time>
+        <speed>0.071383</speed>
+        <name>TP000230</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633546" lon="9.865448057">
+        <ele>77.795921</ele>
+        <time>2010-03-26T00:48:09.400Z</time>
+        <speed>0.081816</speed>
+        <name>TP000231</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633571" lon="9.865447824">
+        <ele>77.794380</ele>
+        <time>2010-03-26T00:48:09.600Z</time>
+        <speed>0.072754</speed>
+        <name>TP000232</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633547" lon="9.865447614">
+        <ele>77.792450</ele>
+        <time>2010-03-26T00:48:09.800Z</time>
+        <speed>0.078225</speed>
+        <name>TP000233</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633489" lon="9.865447399">
+        <ele>77.791138</ele>
+        <time>2010-03-26T00:48:10Z</time>
+        <speed>0.076833</speed>
+        <name>TP000234</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633408" lon="9.865447214">
+        <ele>77.790253</ele>
+        <time>2010-03-26T00:48:10.200Z</time>
+        <speed>0.088488</speed>
+        <name>TP000235</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633317" lon="9.865446987">
+        <ele>77.786873</ele>
+        <time>2010-03-26T00:48:10.400Z</time>
+        <speed>0.103797</speed>
+        <name>TP000236</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633191" lon="9.865446765">
+        <ele>77.784561</ele>
+        <time>2010-03-26T00:48:10.600Z</time>
+        <speed>0.103352</speed>
+        <name>TP000237</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633088" lon="9.865446533">
+        <ele>77.782021</ele>
+        <time>2010-03-26T00:48:10.800Z</time>
+        <speed>0.087818</speed>
+        <name>TP000238</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633048" lon="9.865446282">
+        <ele>77.780220</ele>
+        <time>2010-03-26T00:48:11Z</time>
+        <speed>0.081600</speed>
+        <name>TP000239</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633049" lon="9.865446021">
+        <ele>77.780632</ele>
+        <time>2010-03-26T00:48:11.200Z</time>
+        <speed>0.078945</speed>
+        <name>TP000240</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633074" lon="9.865445763">
+        <ele>77.780319</ele>
+        <time>2010-03-26T00:48:11.400Z</time>
+        <speed>0.083918</speed>
+        <name>TP000241</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633143" lon="9.865445484">
+        <ele>77.779068</ele>
+        <time>2010-03-26T00:48:11.600Z</time>
+        <speed>0.100007</speed>
+        <name>TP000242</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633252" lon="9.865445205">
+        <ele>77.778175</ele>
+        <time>2010-03-26T00:48:11.800Z</time>
+        <speed>0.099195</speed>
+        <name>TP000243</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633370" lon="9.865444927">
+        <ele>77.777702</ele>
+        <time>2010-03-26T00:48:12Z</time>
+        <speed>0.096335</speed>
+        <name>TP000244</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+    <trkseg>
+      <trkpt lat="53.556633474" lon="9.865444640">
+        <ele>77.777336</ele>
+        <time>2010-03-26T00:48:12.200Z</time>
+        <speed>0.097903</speed>
+        <name>TP000245</name>
+        <fix>3d</fix>
+      </trkpt>
+    </trkseg>
+  </trk>
+</gpx>
index 460735b10a4b25d753c49a23f5649fd8dfcb2b86..066ff83b537b8b6b88588035bd9b959a51bbfd70 100644 (file)
@@ -27,3 +27,11 @@ compare ${REFERENCE}/track/trk_reverse_test-rev.gpx ${TMPDIR}/trk_reverse_test-r
 # seg2trk filter test
 gpsbabel -i gpx -f ${REFERENCE}/track/seg2trk_test.gpx -x track,seg2trk -o gpx -F ${TMPDIR}/seg2trk_test-seg.gpx
 compare ${REFERENCE}/track/seg2trk_test-seg.gpx ${TMPDIR}/seg2trk_test-seg.gpx
+
+# Verify that the merge/split code is numerically stable on subsecond input.
+# This would fail on GPSBabel <= 1.4.4 which didn't handle subsecond times
+# correctly in this filter.  Observe that the times in split-split are
+# always ascending and the order of the input track names is preserved.
+
+gpsbabel -i gpx -f ${REFERENCE}/track/split-raw.gpx -x track,merge,split=1m -o gpx -F ${TMPDIR}/split-raw-split.gpx
+compare ${REFERENCE}/track/split-split.gpx ${TMPDIR}/split-raw-split.gpx
index f8c0a01c647a5907e95304928b290be6f0508d0c..b66cab2b980c298914e636de2d6fd85db6dad2aa 100644 (file)
@@ -1,7 +1,7 @@
 /*
 
     Track manipulation filter
-    Copyright (c) 2009, 2010 Robert Lipe, robertlipe@gpsbabel.org
+    Copyright (c) 2009 - 2013 Robert Lipe, robertlipe@gpsbabel.org
     Copyright (C) 2005-2006 Olaf Klein, o.b.klein@gpsbabel.org
 
     This program is free software; you can redistribute it and/or modify
@@ -176,8 +176,8 @@ arglist_t trackfilter_args[] = {
 
 typedef struct trkflt_s {
   route_head *track;
-  time_t first_time;
-  time_t last_time;
+  QDateTime first_time;
+  QDateTime last_time;
 } trkflt_t;
 
 static trkflt_t *track_list = NULL;
@@ -259,8 +259,16 @@ trackfilter_init_qsort_cb(const void *a, const void *b)
 {
   const trkflt_t *ra = (const trkflt_t*) a;
   const trkflt_t *rb = (const trkflt_t*) b;
+  const QDateTime dta = ra->first_time;
+  const QDateTime dtb = rb->first_time;
 
-  return ra->first_time - rb->first_time;
+  if (dta > dtb) {
+    return 1;
+  }
+  if (dta == dtb) {
+    return 0;
+  }
+  return -1;
 }
 
 static int
@@ -268,8 +276,16 @@ trackfilter_merge_qsort_cb(const void *a, const void *b)
 {
   const waypoint *wa = *(waypoint **)a;
   const waypoint *wb = *(waypoint **)b;
+  const QDateTime dta = wa->GetCreationTime();
+  const QDateTime dtb = wb->GetCreationTime();
 
-  return wa->GetCreationTime() - wb->GetCreationTime();
+  if (dta > dtb) {
+    return 1;
+  }
+  if (dta == dtb) {
+    return 0;
+  }
+  return -1;
 }
 
 static fix_type
@@ -366,11 +382,12 @@ trackfilter_fill_track_list_cb(const route_head *track)   /* callback for track_d
 *******************************************************************************/
 
 static void
-trackfilter_split_init_rte_name(route_head *track, const time_t time)
+trackfilter_split_init_rte_name(route_head *track, const QDateTime dt)
 {
   char buff[128], tbuff[128];
   struct tm tm;
 
+  time_t time = dt.toTime_t();
   tm = *localtime(&time);
 
   (opt_interval != 0) ?
@@ -760,8 +777,9 @@ trackfilter_move(void)
       wpt = (waypoint *)elem;
       wpt->creation_time += delta;
     }
-    track_list[i].first_time += delta;
-    track_list[i].last_time += delta;
+
+    track_list[i].first_time = track_list[i].first_time.addSecs(delta);
+    track_list[i].last_time = track_list[i].last_time.addSecs(delta);
   }
 }
 
@@ -1209,7 +1227,7 @@ trackfilter_init(const char *args)
   }
 
   if (count > 0) {
-    track_list = (trkflt_t *) xcalloc(count, sizeof(*track_list));
+    track_list = new trkflt_t[count];
 
     /* check all tracks for time and order (except merging) */
 
@@ -1223,10 +1241,7 @@ trackfilter_init(const char *args)
 static void
 trackfilter_deinit(void)
 {
-  if (track_list != NULL) {
-    xfree(track_list);
-    track_list = NULL;
-  }
+  delete[] track_list;
   track_ct = 0;
   track_pts = 0;
 }